package com.ruoyi.web.controller.app.user;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.ruoyi.app.domain.AppAsset;
import com.ruoyi.app.domain.AppUser;
import com.ruoyi.app.domain.bo.*;
import com.ruoyi.app.domain.vo.AppApplyVo;
import com.ruoyi.app.domain.vo.AppAssetTransferVo;
import com.ruoyi.app.domain.vo.AppAssetVo;
import com.ruoyi.app.domain.vo.AppUserVo;
import com.ruoyi.app.mapper.AppAssetMapper;
import com.ruoyi.app.mapper.AppUserMapper;
import com.ruoyi.app.service.*;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.timeBetween.TradeTimeConfig;
import com.ruoyi.common.utils.timeBetween.TradeTimeUtils;
import com.ruoyi.system.domain.SysNotice;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysNoticeService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * APP用户账单明细
 *
 * @author heise
 * @date 2025-08-31
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/app/apply")
public class AppApplyController extends BaseController {


    private final IAppUserService appUserService;
    private final IAppAssetService appAssetService;
    private final IAppApplyService iAppApplyService;
    private final ISysConfigService sysConfigService;
    private final ISysConfigService iSysConfigService;
    private final ISysNoticeService iSysNoticeService;
    private final IAppLevelRateService appLevelRateService;
    private final IAppAssetTransferService appAssetTransferService;
    private final AppUserMapper appUserMapper;
    private final AppAssetMapper appAssetMapper;


    /**
     * 查询APP用户账单明细列表
     */
    @GetMapping("/page")
    public TableDataInfo<AppApplyVo> page(AppApplyBo bo, PageQuery pageQuery) {
        bo.setUserId(getUserId());
        return iAppApplyService.queryPageList(bo, pageQuery);
    }

    /**
     * 等级手续费列表
     */
    @GetMapping("/list")
    public R<?> list() {
        return R.ok(appLevelRateService.queryList(new AppLevelRateBo()));
    }


    /**
     * 获取APP用户账单明细详细信息
     *
     * @param id 主键
     */
    @GetMapping("/detail")
    public R<AppApplyVo> detail(@RequestParam(name = "id") Long id) {
        return R.ok(iAppApplyService.queryById(id));
    }

    /**
     * 获取APP提现配置参数
     */
    @GetMapping("/withdrawal")
    public R<?> withdrawal() {
        HashMap<String, Object> map = new HashMap<>();
        String rate = iSysConfigService.selectConfigByKey("app.apply.rate");
        SysNotice notice = iSysNoticeService.queryByType("5");
        map.put("rate", rate);
        map.put("describe", notice.getNoticeContent());
        return R.ok(map);
    }

    /**
     * 用户发起提现申请
     */

    @PostMapping("/add")
    public R<Void> add(@Validated(AddGroup.class) AppApplyBo bo) {
        Long id = getUserId();
        AppUserVo myUserVo = appUserService.queryById(id);
        if (!StringUtils.equals(myUserVo.getStatus(), Constants.SUCCESS)) {
            return R.fail("账号已被冻结或注销，请联系客服或管理员！");
        }
        if (StringUtils.isBlank(myUserVo.getCode())) {
            return R.fail("账号先进行实名认证！");
        }
        String one = sysConfigService.selectConfigByKey("app.transfer.one");
        String two = sysConfigService.selectConfigByKey("app.transfer.two");
        TradeTimeConfig config = TradeTimeUtils.createDefaultConfig(one, two);
        TradeTimeUtils service = new TradeTimeUtils(config);
        if (!service.isTradeTimeNow()) {
            return R.fail("当前不在交易时段，禁止操作！");
        }
        //用户提现需要直推日活2人
        //查询今日注册的人
        boolean flag = appUserService.isManRiHuo(id);
        if (!flag){
            return R.fail("今日直推日活数量不足2人，无法提现！");
        }
        bo.setUserId(id);
        String rate = iSysConfigService.selectConfigByKey("app.apply.rate");
        bo.setFreeBalance(bo.getBalance().multiply(new BigDecimal(rate)).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
        bo.setRealityBalance(bo.getBalance().subtract(bo.getFreeBalance()));
        bo.setStatus(Constants.SUCCESS);
        return toAjax(iAppApplyService.applyBalance(bo));
    }

    /**
     * 获取积分兑换贡献度信息
     */
    @GetMapping("/contributionExchangeInfo")
    public R<?> contributionExchangeInfo() {
        Long id = getUserId();
        HashMap<String, Object> map = new HashMap<>();
        String contribution = iSysConfigService.selectConfigByKey("app.exchange.contribution");
        map.put("exchangeRate", contribution);
        AppAssetVo appAssetVo = appAssetService.queryByUid(id);
        map.put("integral", appAssetVo.getIntegral());
        map.put("contribution", appAssetVo.getContribution());
        return R.ok(map);
    }


    /**
     * 积分兑换贡献度
     */

    @PostMapping("/contributionExchange")
    public R<?> contributionExchange(AppApplyBo bo) {
        Long id = getUserId();
        AppUserVo myUserVo = appUserService.queryById(id);
        if (!StringUtils.equals(myUserVo.getStatus(), Constants.SUCCESS)) {
            return R.fail("账号已被冻结或注销，请联系客服或管理员！");
        }
        if (bo.getBalance() == null || bo.getBalance().compareTo(BigDecimal.ZERO) <= 0) {
            return R.fail("兑换数量错误！");
        }
        String contribution = iSysConfigService.selectConfigByKey("app.exchange.contribution");
        BigDecimal integral = bo.getBalance().divide(new BigDecimal(contribution), 2, RoundingMode.HALF_UP);
        AppAssetVo appAssetVo = appAssetService.queryByUid(id);
        if (integral.compareTo(appAssetVo.getIntegral()) > 0) {
            return R.fail("积分不足，无法兑换！");
        }
        Boolean result = iAppApplyService.integralExchange(appAssetVo, integral, bo.getBalance());
        return result ? R.ok("兑换成功") : R.fail("兑换失败！");
    }

    /**
     * 积分转增/余额转赠说明和手续费率
     */
    @GetMapping("/integralTransferInfo")
    public R<?> integralTransferInfo() {
        Long id = getUserId();
        HashMap<String, Object> map = new HashMap<>();
        AppAssetVo appAssetVo = appAssetService.queryByUid(id);
        map.put("balance", appAssetVo.getBalance());
        map.put("integral", appAssetVo.getIntegral());
        //当前等级手续费，减去减免手续费=最终手续费
        BigDecimal rate = appLevelRateService.userRate(id);
        AppUserVo userVo = appUserService.queryById(id);
        BigDecimal reduceLv = userVo.getReduceLv() == null ? BigDecimal.ZERO : new BigDecimal(userVo.getReduceLv());
        BigDecimal subtract = rate.subtract(reduceLv);
        map.put("transferRate", subtract.compareTo(BigDecimal.ZERO) > 0 ? subtract : BigDecimal.ZERO);
        return R.ok(map);
    }

    /**
     * 转赠的账单记录
     */
    @GetMapping("/transferPage")
    public TableDataInfo<AppAssetTransferVo> transferPage(AppAssetTransferBo bo, PageQuery pageQuery) {
        if (StringUtils.equals(Constants.SUCCESS, bo.getOrderType())) {
            bo.setUserId(getUserId());
        } else {
            bo.setToUserId(getUserId());
        }
        ArrayList<String> list = new ArrayList<>();
        if (StringUtils.equals(Constants.TWO, bo.getStatus())) {
            list.add(Constants.TWO);
        } else {
            list.add(Constants.SUCCESS);
            list.add(Constants.FAIL);
        }
        bo.setStatus(null);
        bo.setStatusList(list);
        TableDataInfo<AppAssetTransferVo> page = appAssetTransferService.queryPageList(bo, pageQuery);
        page.getData().forEach(e -> {
            Long userId = e.getUserId();
            AppUserVo userVo = appUserService.queryById(userId);
            AppUserVo toUserId = appUserService.queryById(e.getUserId());
            e.setPhone1(userVo.getPhone());
            String mobile = e.getPhone();
            e.setPhone(mobile);
            e.setCreateTimeFormat(DateUtil.format(e.getCreateTime(), "yyyy.MM.dd HH:mm"));
            e.setVoucherTimeOut(0L);
            if (StringUtils.equals(e.getStatus(), Constants.FAIL)) {
                e.setVoucherTimeOut(DateUtil.offsetMinute(e.getVoucherTime(), 60).getTime() / 1000L);
            }
            e.setAliImg(toUserId.getAliImg());
            e.setWxImg(toUserId.getWxImg());
            e.setBankCode(toUserId.getBankCode());
            e.setBankName(toUserId.getBankName());
            e.setBankType(toUserId.getBankType());
        });
        return page;
    }


    /**
     * 余额转赠
     */

    @PostMapping("/integralTransfer")
    public R<?> integralTransfer(@Validated(AddGroup.class) AppTransferBo transferBo) {
        Long id = getUserId();
        AppUserVo myUserVo = appUserService.queryById(id);
        if (!StringUtils.equals(myUserVo.getStatus(), Constants.SUCCESS)) {
            return R.fail("账号已被冻结或注销，请联系客服或管理员！");
        }
        if (StringUtils.isBlank(myUserVo.getCode())) {
            return R.fail("账号先进行实名认证！");
        }
        String open = sysConfigService.selectConfigByKey("app.transfer.open");
        if (!StringUtils.equals(Constants.FAIL, open)) {
            return R.fail("转赠功能暂未开放！");
        }
        String one = sysConfigService.selectConfigByKey("app.transfer.one");
        String two = sysConfigService.selectConfigByKey("app.transfer.two");
        TradeTimeConfig config = TradeTimeUtils.createDefaultConfig(one, two);
        TradeTimeUtils service = new TradeTimeUtils(config);
        if (!service.isTradeTimeNow()) {
            return R.fail("当前不在交易时段，禁止操作！");
        }

        AppUserVo userVo = appUserService.queryById(transferBo.getUserId());
        if (Objects.isNull(userVo)) {
            return R.fail("用户不存在！");
        }
        if (id.equals(userVo.getId())) {
            return R.fail("不能转赠给自己！");
        }
        BigDecimal balance = transferBo.getBalance().abs();
        AppAssetVo assetVo = appAssetService.queryByUid(id);
        if (balance.compareTo(assetVo.getBalance()) > 0) {
            return R.fail("余额不足！");
        }
        BigDecimal rate = appLevelRateService.userRate(id);
        AppAssetTransferBo transfer = appAssetTransferService.createTransfer(id, userVo, balance, rate);
        return Objects.nonNull(transfer) ? R.ok("转赠成功", transfer) : R.fail("转赠失败！");
    }

    /**
     * 冻结
     */

    @PostMapping("/freeze")
    public R<?> freeze(@Validated(AddGroup.class) AppUserFreeBo appUserFreeBo) {
        return R.result(appAssetTransferService.freeze(appUserFreeBo));
    }

    /**
     * 积分转赠
     */

    @PostMapping("/balanceTransfer")
    public R<?> balanceTransfer(@Validated(AddGroup.class) AppTransferBo transferBo) {
        Long id = getUserId();
        AppUserVo myUserVo = appUserService.queryById(id);
        if (!StringUtils.equals(myUserVo.getStatus(), Constants.SUCCESS)) {
            return R.fail("账号已被冻结或注销，请联系客服或管理员！");
        }
        if (StringUtils.isBlank(myUserVo.getCode())) {
            return R.fail("账号先进行实名认证！");
        }
        String open = sysConfigService.selectConfigByKey("app.transfer.open");
        if (!StringUtils.equals(Constants.FAIL, open)) {
            return R.fail("转赠功能暂未开放！");
        }
        String one = sysConfigService.selectConfigByKey("app.transfer.one");
        String two = sysConfigService.selectConfigByKey("app.transfer.two");
        TradeTimeConfig config = TradeTimeUtils.createDefaultConfig(one, two);
        TradeTimeUtils service = new TradeTimeUtils(config);
        if (!service.isTradeTimeNow()) {
            return R.fail("当前不在交易时段，禁止操作！");
        }
        AppUserVo userVo = appUserService.queryById(transferBo.getUserId());
        if (Objects.isNull(userVo)) {
            return R.fail("用户不存在！");
        }
        if (id.equals(userVo.getId())) {
            return R.fail("不能转赠给自己！");
        }

        boolean flag = appUserService.isManRiHuo(id);
        if (!flag){
            return R.fail("今日直推日活数量不足2人，无法提现！");
        }

        //对方也需要实名
        if (StringUtils.isBlank(userVo.getCode())) {
            return R.fail("对方先进行实名认证！");
        }

        BigDecimal balance = transferBo.getBalance().abs();
        AppAssetVo assetVo = appAssetService.queryByUid(id);
        if (balance.compareTo(assetVo.getIntegral()) > 0) {
            return R.fail("积分不足！");
        }

        if (assetVo.getFreezeFlag()==1){
            return R.fail("积分已被冻结，请解冻后再操作！");
        }

        BigDecimal rate = appLevelRateService.userRate(id);
        if (balance.compareTo(assetVo.getContribution()) > 0) {
             return R.fail("贡献值不足！");
        }

        AppAssetTransferBo transfer = appAssetTransferService.createTransferIntegral(id, userVo, balance, rate);
        return Objects.nonNull(transfer) ? R.ok("转赠成功", transfer) : R.fail("转赠失败！");
    }


    /**
     * 积分/余额转赠取消
     */

    @PostMapping("/cancelTransfer")
    public R<?> cancelTransfer(AppAssetTransferBo transferBo) {
        if (transferBo.getTransferId() == null) {
            return R.fail("订单ID不能为空！");
        }
        AppAssetTransferVo transferVo = appAssetTransferService.queryById(transferBo.getTransferId());
        if (Objects.isNull(transferVo)) {
            return R.fail("订单不存在！");
        }
        if (!StringUtils.equals(transferVo.getStatus(), Constants.SUCCESS)) {
            return R.fail("订单已交易，无法取消！");
        }
        return R.result(appAssetTransferService.cancelTransfer(transferVo));
    }

    /**
     * 买家上传凭证
     */

    @PostMapping("/uploadVoucher")
    public R<?> uploadVoucher(AppAssetTransferBo transferBo) {
        if (transferBo.getTransferId() == null) {
            return R.fail("请选择要上传凭证的订单！");
        }
        if (StringUtils.isBlank(transferBo.getVoucher())) {
            return R.fail("凭证不能为空！");
        }
        AppAssetTransferVo transferVo = appAssetTransferService.queryById(transferBo.getTransferId());
        if (Objects.isNull(transferVo)) {
            return R.fail("订单不存在！");
        }
        Long id = getUserId();
        if (!id.equals(transferVo.getToUserId())) {
            return R.fail("赠送人错误，无权上传凭证");
        }
        if (!transferVo.getStatus().equals(Constants.SUCCESS) && !transferVo.getStatus().equals(Constants.FAIL)) {
            return R.fail("订单已处理，无法上传凭证！");
        }
        AppAssetTransferBo appAssetTransferBo = new AppAssetTransferBo();
        appAssetTransferBo.setStatus(Constants.FAIL);
        appAssetTransferBo.setVoucher(transferBo.getVoucher());
        appAssetTransferBo.setTransferId(transferBo.getTransferId());
        appAssetTransferBo.setVoucherTime(DateUtils.getNowDate());
        return R.result(appAssetTransferService.update(appAssetTransferBo));
    }


    /**
     * 卖家确定转赠
     */

    @PostMapping("/confirmTransfer")
    @RepeatSubmit
    public R<?> confirmTransfer(AppAssetTransferBo transferBo) {
        if (transferBo.getTransferId() == null) {
            return R.fail("ID不能为空！");
        }
        AppAssetTransferVo transferVo = appAssetTransferService.queryById(transferBo.getTransferId());
        if (Objects.isNull(transferVo)) {
            return R.fail("订单不存在！");
        }
        Long id = getUserId();
        if (!id.equals(transferVo.getUserId())) {
            return R.fail("用户无权操作订单");
        }
        if (StringUtils.equals(transferVo.getAppealStatus(), Constants.FAIL)) {
            return R.fail("订单已被申诉！");
        }
        if (!transferVo.getStatus().equals(Constants.FAIL)) {
            return R.fail("订单已处理！");
        }
        return R.result(appAssetTransferService.confirmTransfer(transferVo));
    }

    /**
     * 申诉功能
     */

    @PostMapping("/appealTransfer")
    public R<?> appealTransfer(AppAssetTransferBo transferBo) {
        if (transferBo.getTransferId() == null) {
            return R.fail("ID不能为空！");
        }
        AppAssetTransferVo transferVo = appAssetTransferService.queryById(transferBo.getTransferId());
        if (Objects.isNull(transferVo)) {
            return R.fail("订单不存在！");
        }
        Long id = getUserId();
        if (!id.equals(transferVo.getUserId()) && !id.equals(transferVo.getToUserId())) {
            return R.fail("用户无权操作订单");
        }
        if (StringUtils.equals(transferVo.getAppealStatus(), Constants.FAIL)) {
            return R.fail("订单已被申诉！");
        }
        if (!transferVo.getStatus().equals(Constants.FAIL)) {
            return R.fail("订单状态无法申诉！");
        }
        if (!transferVo.getAppealStatus().equals(Constants.SUCCESS)) {
            return R.fail("订单已申诉，无法重复申诉！");
        }
        AppAssetTransferBo appAssetTransferBo = new AppAssetTransferBo();
        appAssetTransferBo.setTransferId(transferBo.getTransferId());
        appAssetTransferBo.setAppealStatus(Constants.FAIL);
        return R.result(appAssetTransferService.update(appAssetTransferBo));
    }


    /**
     * 根据手机号查询用户
     *
     * @param phone 用户手机号
     * @return
     */
    @GetMapping("/queryPhone")
    public R<?> queryPhone(String phone) {
        AppUserVo userVo = appUserService.queryByPhone(phone);
        if (Objects.nonNull(userVo)) {
            HashMap<String, Object> map = new HashMap<>();
            map.put("userId", userVo.getId());
            map.put("phone", phone);
            map.put("avatar", userVo.getAvatar());
            map.put("nickName", userVo.getNickName());
            return R.ok(map);
        }
        return R.fail("未查询到用户！");
    }


}
